package hhtc.jsjds.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import hhtc.jsjds.constant.RedisKey;
import hhtc.jsjds.entity.*;
import hhtc.jsjds.enums.StatusCodeEnum;
import hhtc.jsjds.exception.XscoderException;
import hhtc.jsjds.mapper.*;
import hhtc.jsjds.redis.RedisProvider;
import hhtc.jsjds.service.CompetitionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
public class CompetitionServiceImpl implements CompetitionService {


    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    TeamMapper teamMapper;

    @Autowired
    StudentMapper studentMapper;

    @Autowired
    WorksMapper worksMapper;

    @Autowired
    FinalTeamMapper finalTeamMapper;

    @Autowired
    private RedisProvider redisProvider;

    private String enroll_endtime;


    @Override
    public List<Category> getAllCategories() {
        Example example = new Example(Category.class);
        example.createCriteria().andEqualTo("parent_id", "0");
        List<Category> categories = categoryMapper.selectByExample(example);
        for (Category category : categories) {
            Category category1 = new Category();
            category1.setParent_id(category.getId());
            category.setCategories(categoryMapper.select(category1));
        }
        return categories;
    }

    @Override
    @Transactional
    public boolean insertNewTeam(Team team) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            enroll_endtime = redisProvider.get(RedisKey.ENROLL_END_TIME);
            Date endtime = sdf.parse(enroll_endtime);
            Date now = new Date();
            if (endtime.before(now)) {
                throw new XscoderException(StatusCodeEnum.ENROLL_HAS_ENDED);
            }
        } catch (Exception e) {
            throw new XscoderException(StatusCodeEnum.PARSE_TIME_FAILED);
        }
        Student student = new Student();
        student.setUid(team.getUid());
        student = studentMapper.selectOne(student);
        if (student.getMajor_id() == null) {
            throw new XscoderException(StatusCodeEnum.INFO_NOT_COMPLETED);
        }
        //查询哪些专业可以报名 category_A 这个比赛
        List<Integer> cate = teamMapper.getAllowList(team.getCategoryA_id());
        //如果不包含在里面 则会返回错误提示
        if (cate.size() != 0 && !cate.contains(Integer.parseInt(student.getMajor_id()))) {
            throw new XscoderException(StatusCodeEnum.MAJOR_HAS_LIMITED);
        }
        if (StringUtils.isBlank(student.getAcademy_id())
                || StringUtils.isBlank(student.getMajor_id())
                || StringUtils.isBlank(student.getStu_idCard())) {
            throw new XscoderException(StatusCodeEnum.INFO_NOT_COMPLETED);
        }
        List<Integer> list = teamMapper.getCategories(student.getUid());
        if (list != null && list.contains(Integer.parseInt(team.getCategoryA_id()))) {
            throw new XscoderException(StatusCodeEnum.COUNT_LIMIT_ERROR);
        }
        if (teamMapper.CountTeamByUid(team.getUid()) >= 2) {
            throw new XscoderException(StatusCodeEnum.COUNT_TOTALLIMIT_ERROR);
        }
        //判断专业学生不能报名非专业组
        if (teamMapper.testAuth(student.getMajor_id(), team.getCategoryA_id()) != 0) {
            throw new XscoderException(StatusCodeEnum.MAJOR_NOT_SATISFIED);
        }

        try {
            teamMapper.insert(team);
            teamMapper.insert2link(team.getUid(), team.getId(), "1");
        } catch (Exception e) {
            e.printStackTrace();
            throw new XscoderException(StatusCodeEnum.OPT_FAILD);
        }
        return true;
    }

    @Override
    public List<Team> GetUserOwnTeams(String uid) {
        Team team = new Team();
        team.setUid(uid);
        List<Team> select = teamMapper.select(team);
        for (Team team1 : select) {
            team1.setCategoryA(categoryMapper.selectByPrimaryKey(team1.getCategoryA_id()));
            team1.setCategoryB(categoryMapper.selectByPrimaryKey(team1.getCategoryB_id()));
        }
        return select;
    }

    @Override
    public List<Team> GetUserOtherTeams(String uid) {
        List<Team> teams = teamMapper.GetUserOtherTeams(uid);
        for (Team team1 : teams) {
            team1.setCategoryA(categoryMapper.selectByPrimaryKey(team1.getCategoryA_id()));
            team1.setCategoryB(categoryMapper.selectByPrimaryKey(team1.getCategoryB_id()));
        }
        return teams;
    }

    @Override
    @Transactional
    public boolean StudentAddTeam(String uid, String invitation_code) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //判断是否超过报名时间
        try {
            enroll_endtime = redisProvider.get(RedisKey.ENROLL_END_TIME);
            Date endtime = sdf.parse(enroll_endtime);
            Date now = new Date();
            if (endtime.before(now)) {
                throw new XscoderException(StatusCodeEnum.ENROLL_HAS_ENDED);
            }
        } catch (ParseException e) {
            throw new XscoderException(StatusCodeEnum.PARSE_TIME_FAILED);
        }
        Team team = new Team();
        team.setInvitation_code(invitation_code);
        team = teamMapper.selectOne(team);

        //判断邀请码是否正确
        if (team == null) {
            throw new XscoderException(StatusCodeEnum.WRONG_INV_CODE);
        }
        //判断学生是否超过2个队伍限制
        if (teamMapper.CountTeamByUid(uid) >= 2) {
            throw new XscoderException(StatusCodeEnum.COUNT_TOTALLIMIT_ERROR);
        }
        Student student = new Student();
        student.setUid(uid);
        //判断学生是否存在于同一大类中
        List<Integer> list = teamMapper.getCategories(student.getUid());
        if (list.size() != 0 && list.contains(Integer.parseInt(team.getCategoryA_id()))) {
            throw new XscoderException(StatusCodeEnum.COUNT_LIMIT_ERROR);
        }
        //判断队伍人数是否已满
        Category category = categoryMapper.selectByPrimaryKey(team.getCategoryA_id());
        int count = teamMapper.CountStuByTid(team.getId());
        if (count == category.getCount_limit()) {
            throw new XscoderException(StatusCodeEnum.TEAM_HAS_FULL);
        }
        //判断学生信息是否完整
        student = studentMapper.selectOne(student);
        if (StringUtils.isBlank(student.getAcademy_id())
                || StringUtils.isBlank(student.getMajor_id())
                || StringUtils.isBlank(student.getStu_idCard())) {
            throw new XscoderException(StatusCodeEnum.INFO_NOT_COMPLETED);
        }
        //判断所选类别是否有专业限制
        if (teamMapper.testAuth(student.getMajor_id(), team.getCategoryA_id()) != 0) {
            throw new XscoderException(StatusCodeEnum.MAJOR_NOT_SATISFIED);
        }
        return teamMapper.insert2link(uid, team.getId(), count + 1 + "") == 1;
    }

    @Override
    public boolean deleteTeam(String uid, String tid) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            enroll_endtime = redisProvider.get(RedisKey.ENROLL_END_TIME);
            Date endtime = sdf.parse(enroll_endtime);
            Date now = new Date();
            if (endtime.before(now)) {
                throw new XscoderException(StatusCodeEnum.CHANGE_NOT_ALLOWED);
            }
        } catch (ParseException e) {
            throw new XscoderException(StatusCodeEnum.PARSE_TIME_FAILED);
        }
        Example example = new Example(Team.class);
        example.createCriteria().andEqualTo("id", tid)
                .andEqualTo("uid", uid);
        if (teamMapper.deleteByExample(example) == 1) {
            teamMapper.delete2link(tid);
            teamMapper.deleteTeamWorks(tid);
        } else {
            throw new XscoderException(StatusCodeEnum.OPT_FAILD);
        }

        return false;
    }

    @Override
    public List<Student> getTeamMate(String uid, String tid) {

        List<Integer> uids = teamMapper.getTeamUids(tid);
        for (Integer i : uids) {
            if (i == Integer.parseInt(uid)) {
                return teamMapper.getTeamMate(tid);
            }
        }
        throw new XscoderException(StatusCodeEnum.OPT_FAILD);
    }

    @Override
    @Transactional
    public boolean userExitTeam(String uid, String tid) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            enroll_endtime = redisProvider.get(RedisKey.ENROLL_END_TIME);
            Date endtime = sdf.parse(enroll_endtime);
            Date now = new Date();
            if (endtime.before(now)) {
                throw new XscoderException(StatusCodeEnum.CHANGE_NOT_ALLOWED);
            }
        } catch (ParseException e) {
            throw new XscoderException(StatusCodeEnum.PARSE_TIME_FAILED);
        }
        if (teamMapper.userExitTeam(uid, tid) != 1) {
            throw new XscoderException(StatusCodeEnum.EXIT_HAS_FAILED);
        }
        return true;
    }

    @Override
    @Transactional
    public boolean changeTeamMateIndex(String uid, String tid) {
        //获取当前队伍人数
        List<TeamMateSeq> list = teamMapper.getTeamIndex(tid);
        Team team = teamMapper.selectByPrimaryKey(tid);
        Category category = categoryMapper.selectByPrimaryKey(team.getCategoryA_id());
        if (category.getCount_limit() > 3) {
            throw new XscoderException(StatusCodeEnum.COUNT_ERROR);
        }
        int count = list.size();
        if (count == 1 || count == 2) {
            throw new XscoderException(StatusCodeEnum.CHANGE_NOT_SATISFIED);
        }
        for (TeamMateSeq teamMateSeq : list) {
            if (teamMateSeq.getUid().equals(uid) && teamMateSeq.getIndex() != 1) {
                throw new XscoderException(StatusCodeEnum.BAD_REQUEST);
            }
            if (teamMateSeq.getIndex() == 2) {
                if (teamMapper.saveTeamIndex(teamMateSeq.getUid(), "3", tid) != 1) {
                    throw new XscoderException(StatusCodeEnum.BAD_REQUEST);
                }
                continue;
            }
            if (teamMateSeq.getIndex() == 3) {
                if (teamMapper.saveTeamIndex(teamMateSeq.getUid(), "2", tid) != 1) {
                    throw new XscoderException(StatusCodeEnum.BAD_REQUEST);
                }
            }
        }
        return true;
    }

    @Override
    public boolean setTeamEliminatedByWid(String wid) {
        Works works = new Works();
        works.setId(wid);
        works = worksMapper.selectOne(works);
        works.setState("2");
        return worksMapper.updateByPrimaryKey(works) == 1;
    }

    @Override
    public PageInfo<Works> sysAdminGetAllWorks(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        PageInfo<Works> pageInfo = new PageInfo<>(worksMapper.sysAdminGetAllWorks());
        return pageInfo;
    }

    @Override
    public boolean setTeamPassedByWid(String wid) {
        Works works = new Works();
        works.setId(wid);
        works = worksMapper.selectOne(works);
        works.setState("1");
        return worksMapper.updateByPrimaryKey(works) == 1;
    }

    @Override
    public void randomSort() {
        this.random("1");//随机生成第一答辩场顺序
        this.random("2");//随机生成第二答辩场顺序
    }

    @Override
    public Works getWorksByTeamId(String uid, Integer team_id) {
        List<Works> worksByTeamId = worksMapper.getWorksByTeamId(uid, team_id + "");
        if (worksByTeamId.size() > 0 && worksByTeamId.get(0) != null) {
            return worksByTeamId.get(0);
        } else {
            throw new XscoderException(StatusCodeEnum.TEAM_NOT_FOUND);
        }
    }

    public void random(String area) {
        Example example = new Example(FinalTeam.class);//获取对应答辩场所有队伍
        example.createCriteria().andEqualTo("area", area);//获取对应答辩场所有队伍
        List<FinalTeam> finalTeams = finalTeamMapper.selectByExample(example);//获取对应答辩场所有队伍
        Random random = new Random();//生成随机生成器
        boolean[] isSeq = new boolean[finalTeams.size() + 1];//标记已排序的队伍
        for (int i = 1; i <= finalTeams.size(); i++) {//对所有队伍逐一随机排序，i为出场顺序
            int team_id;
            while (true) {
                team_id = random.nextInt(finalTeams.size());//随机选择一个队伍编号，使其在i位置出场
                if (!isSeq[team_id]) {//如果该队伍已排序，则继续随机
                    break;
                }
            }
            isSeq[team_id] = true;//标记该队伍已排序
            finalTeams.get(team_id).setSequence(i + "");//将信息保存至数据库
            finalTeamMapper.updateByPrimaryKey(finalTeams.get(team_id));//将信息保存至数据库
            System.out.println("答辩场" + area + ":第" + i + "出场队伍编号为:" + finalTeams.get(team_id).getTeam_id());//输出
        }
    }

}
